package com.ruoyi.water.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.water.domain.Element;
import com.ruoyi.water.domain.Leakage;
import com.ruoyi.water.domain.MeterAnalyse;
import com.ruoyi.water.mapper.ElementMapper;
import com.ruoyi.water.mapper.LeakageMapper;
import com.ruoyi.water.mapper.MeterAnalyseMapper;
import com.ruoyi.water.service.ILeakageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 漏耗分析Service实现类
 *
 * @author ruoyi
 * @date 2025-09-29
 */
@Service
public class LeakageServiceImpl extends ServiceImpl<LeakageMapper, Leakage> implements ILeakageService {

    @Autowired
    private ElementMapper elementMapper;

    @Autowired
    private MeterAnalyseMapper meterAnalyseMapper;

    /**
     * 计算指定日期范围内的漏耗数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int calculateLeakageByDateRange(Date startDate, Date endDate) {
        int count = 0;

        // 校验日期参数
        if (startDate == null || endDate == null || startDate.after(endDate)) {
            throw new IllegalArgumentException("无效的日期范围");
        }

        // 遍历日期范围内的每一天
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);

        while (!calendar.getTime().after(endDate)) {
            Date currentDate = calendar.getTime();

            // 计算当前日期的漏耗数据
            Leakage leakage = calculateDailyLeakage(currentDate);

            if (leakage != null) {
                // 保存漏耗数据
                saveOrUpdate(leakage);
                count++;
            }

            // 日期加1天
            calendar.add(Calendar.DATE, 1);
        }

        return count;
    }

    /**
     * 计算单天的漏耗数据
     */
    private Leakage calculateDailyLeakage(Date date) {
        // 1. 查询elemLevel=1且ismonitor=true的一级表元素
        QueryWrapper<Element> firstLevelQuery = new QueryWrapper<>();
        firstLevelQuery.eq("elemLevel", 1)
                .eq("ismonitor", true);
        List<Element> firstLevelElements = elementMapper.selectList(firstLevelQuery);

        // 2. 计算一级表todayUsage总和
        double firstLevelSum = 0.0;
        if (firstLevelElements != null && !firstLevelElements.isEmpty()) {
            for (Element element : firstLevelElements) {
                QueryWrapper<MeterAnalyse> meterAnalyseQuery = new QueryWrapper<>();
                meterAnalyseQuery.eq("meterId", element.getId())
                        .eq("analyseDate", date);

                MeterAnalyse meterAnalyse = meterAnalyseMapper.selectOne(meterAnalyseQuery);
                if (meterAnalyse != null && meterAnalyse.getTodayUsage() != null) {
                    firstLevelSum += meterAnalyse.getTodayUsage();
                }
            }
        }

        // 避免除零异常
        if (firstLevelSum <= 0) {
            return null;
        }

        // 3. 查询elemLevel=2且ismonitor=true的二级表元素
        QueryWrapper<Element> secondLevelQuery = new QueryWrapper<>();
        secondLevelQuery.eq("elemLevel", 2)
                .eq("ismonitor", true);
        List<Element> secondLevelElements = elementMapper.selectList(secondLevelQuery);

        // 4. 计算二级表todayUsage总和
        double secondLevelSum = 0.0;
        if (secondLevelElements != null && !secondLevelElements.isEmpty()) {
            for (Element element : secondLevelElements) {
                QueryWrapper<MeterAnalyse> meterAnalyseQuery = new QueryWrapper<>();
                meterAnalyseQuery.eq("meterId", element.getId())
                        .eq("analyseDate", date);

                MeterAnalyse meterAnalyse = meterAnalyseMapper.selectOne(meterAnalyseQuery);
                if (meterAnalyse != null && meterAnalyse.getTodayUsage() != null) {
                    secondLevelSum += meterAnalyse.getTodayUsage();
                }
            }
        }

        // 5. 计算漏耗值和漏耗占比
        double leakageValue = firstLevelSum - secondLevelSum;
        double leakagePercent = leakageValue / firstLevelSum;

        // 6. 构建漏耗实体
        Leakage leakage = new Leakage();
        leakage.setLeakageType(1); // 默认类型
        leakage.setLeakageValue(leakageValue);
        leakage.setLeakagePercent(leakagePercent);
        leakage.setAnalyseDate(date);
        leakage.setStatus(false); // 默认状态
        leakage.setRecordDate(new Date()); // 记录当前时间

        return leakage;
    }
}
